import mysql.connector
from mysql.connector import Error


def mensagem_duplicidade(erro):
    texto = str(erro).lower()
    if "cpf" in texto:
        return "Não foi possível registrar o paciente, pois já existe um paciente cadastrado com esse CPF."
    if "telefone" in texto:
        return "Não foi possível registrar o paciente, pois já existe um paciente cadastrado com esse telefone."
    return "Não foi possível salvar: valor duplicado em um campo único."



class Paciente:


    def __init__(self, nome, cpf, data_nascimento, telefone, endereco, id_paciente=None):
        self.id_paciente = id_paciente
        self.nome = nome
        self.cpf = cpf
        self.data_nascimento = data_nascimento
        self.telefone = telefone
        self.endereco = endereco


    def __str__(self):
        return (f"[{self.id_paciente}] {self.nome} | CPF: {self.cpf} | "
                f"Nascimento: {self.data_nascimento} | Telefone: {self.telefone} | "
                f"Endereço: {self.endereco}")


class BancoDados:


    def __init__(self, host="localhost", user="administrador",
                 password="admin", database="ProjetoPosto"):
        self.host = host
        self.user = user
        self.password = password
        self.database = database
        self.conexao = None


    def conectar(self):
        try:
            self.conexao = mysql.connector.connect(
                host=self.host,
                user=self.user,
                password=self.password,
                database=self.database
            )
            print("Conexão com o banco de dados bem-sucedida.")
        except Error as erro:
            print(f"Erro ao se conectar no banco de dados: {erro}")
            self.conexao = None


    def desconectar(self):
        if self.conexao:
            self.conexao.close()
            print("A conexão com o MySQL foi fechada.")


    def inserir(self, paciente):
        cursor = self.conexao.cursor()
        sql = ("INSERT INTO Paciente (nome, cpf, data_nascimento, telefone, endereco) "
               "VALUES (%s, %s, %s, %s, %s)")
        valores = (paciente.nome, paciente.cpf, paciente.data_nascimento,
                   paciente.telefone, paciente.endereco)
        try:
            cursor.execute(sql, valores)
            self.conexao.commit()
            print(f"{cursor.rowcount} registro(s) inserido(s).")
        except Error as erro:
            self.conexao.rollback()
            if erro.errno == 1062:
                print(mensagem_duplicidade(erro))
            else:
                print(f"Erro ao inserir paciente: {erro}")
        finally:
            cursor.close()


    def listar(self):
        cursor = self.conexao.cursor()
        cursor.execute(
            "SELECT id_paciente, nome, cpf, data_nascimento, telefone, endereco "
            "FROM Paciente"
        )
        resultado = cursor.fetchall()
        cursor.close()

        pacientes = []
        for id_paciente, nome, cpf, data_nascimento, telefone, endereco in resultado:
            pacientes.append(Paciente(nome, cpf, data_nascimento, telefone, endereco, id_paciente))
        return pacientes


    def buscar_por_id(self, id_paciente):
        cursor = self.conexao.cursor()
        cursor.execute(
            "SELECT id_paciente, nome, cpf, data_nascimento, telefone, endereco "
            "FROM Paciente WHERE id_paciente = %s",
            (id_paciente,)
        )
        registro = cursor.fetchone()
        cursor.close()

        if registro:
            return Paciente(registro[1], registro[2], registro[3],
                             registro[4], registro[5], registro[0])
        return None


    def atualizar(self, paciente):
        cursor = self.conexao.cursor()
        sql = ("UPDATE Paciente SET nome = %s, cpf = %s, data_nascimento = %s, "
               "telefone = %s, endereco = %s WHERE id_paciente = %s")
        valores = (paciente.nome, paciente.cpf, paciente.data_nascimento,
                   paciente.telefone, paciente.endereco, paciente.id_paciente)
        try:
            cursor.execute(sql, valores)
            self.conexao.commit()
            print(f"{cursor.rowcount} registro(s) atualizado(s).")
        except Error as erro:
            self.conexao.rollback()
            if erro.errno == 1062:
                print(mensagem_duplicidade(erro))
            else:
                print(f"Erro ao atualizar registro de paciente: {erro}")
        finally:
            cursor.close()

    def remover(self, id_paciente):
        cursor = self.conexao.cursor()
        try:
            cursor.execute(
                "DELETE FROM Paciente WHERE id_paciente = %s",
                (id_paciente,)
            )
            self.conexao.commit()
            print(f"{cursor.rowcount} registro(s) removido(s).")
        except Error as erro:
            self.conexao.rollback()
            if erro.errno == 1451: 
                print("Não foi possível remover: existem agendamentos ou aplicações de vacina "
                      "vinculados a esse paciente.")
            else:
                print(f"Erro ao remover paciente: {erro}")
        finally:
            cursor.close()



def menu_adicionar(bd):
    nome = input("Nome: ")
    cpf = input("CPF (11 dígitos): ")
    data_nascimento = input("Data de nascimento (AAAA-MM-DD): ")
    telefone = input("Telefone: ")
    endereco = input("Endereço: ")
    novo = Paciente(nome, cpf, data_nascimento, telefone, endereco)
    bd.inserir(novo)


def menu_listar(bd):
    for paciente in bd.listar():
        print(paciente)


def menu_buscar(bd):
    id_paciente = input("\nDigite o ID do paciente: ")
    paciente = bd.buscar_por_id(id_paciente)
    if paciente:
        print(paciente)
    else:
        print("\nO paciente não foi encontrado.")
    return paciente


def menu_atualizar(bd):
    paciente = menu_buscar(bd)
    if paciente:
        print("\nDeixe em branco para manter o dado atual.\n")
        nome = input(f"Nome [{paciente.nome}]: ")
        cpf = input(f"CPF [{paciente.cpf}]: ")
        data_nascimento = input(f"Data de nascimento [{paciente.data_nascimento}]: ")
        telefone = input(f"Telefone [{paciente.telefone}]: ")
        endereco = input(f"Endereço [{paciente.endereco}]: ")

        paciente.nome = nome or paciente.nome
        paciente.cpf = cpf or paciente.cpf
        paciente.data_nascimento = data_nascimento or paciente.data_nascimento
        paciente.telefone = telefone or paciente.telefone
        paciente.endereco = endereco or paciente.endereco

        bd.atualizar(paciente)


def menu_remover(bd):
    id_paciente = input("\nID do paciente a remover: ")
    bd.remover(id_paciente)


def menu_principal():
    bd = BancoDados()
    bd.conectar()

    if not bd.conexao:
        return

    while True:
        print("\nCADASTRO DE PACIENTES\n")
        print("1 - Adicionar paciente")
        print("2 - Listar todos os pacientes")
        print("3 - Buscar paciente")
        print("4 - Atualizar cadastro de paciente")
        print("5 - Remover paciente")
        print("0 - Sair")

        opcao = input("\nEscolha uma opção: ")

        if opcao == "1":
            menu_adicionar(bd)
        elif opcao == "2":
            menu_listar(bd)
        elif opcao == "3":
            menu_buscar(bd)
        elif opcao == "4":
            menu_atualizar(bd)
        elif opcao == "5":
            menu_remover(bd)
        elif opcao == "0":
            print("Encerrando...")
            break
        else:
            print("Opção inválida. Digite uma opção (válida) novamente.")

    bd.desconectar()



if __name__ == "__main__":
    menu_principal()


MANIPULAÇÃO DA TABELA ‘ESPECIALIDADE’

import mysql.connector
from mysql.connector import Error

class Especialidade:
    def __init__(self, descricao, id_especialidade=None):
        self.id_especialidade = id_especialidade
        self.descricao = descricao

    def __str__(self):
        return "[%s] %s" % (self.id_especialidade, self.descricao)

class BancoDados:
    def __init__(self, host="localhost", user="administrador",
                 password="admin", database="ProjetoPosto"):
        self.host = host
        self.user = user
        self.password = password
        self.database = database
        self.conexao = None

    def conectar(self):
        try:
            self.conexao = mysql.connector.connect(
                host=self.host,
                user=self.user,
                password=self.password,
                database=self.database
            )
            print("Conexão com o banco de dados bem sucedida!")
        except Error as erro:
            print(f"Ocorreu um erro ao se conectar ao banco de dados: {erro}")
            self.conexao = None

    def desconectar(self):
        if self.conexao:
            self.conexao.close()
            print("A conexão com o MySQL foi fechada!")

    def inserir(self, especialidade):
        cursor = self.conexao.cursor()
        sql = "INSERT INTO Especialidade (descricao) VALUES (%s)"
        cursor.execute(sql, (especialidade.descricao,))
        self.conexao.commit()
        print("%s registro inserido." % cursor.rowcount)
        cursor.close()

    def listar(self):
        cursor = self.conexao.cursor()
        cursor.execute("SELECT id_especialidade, descricao FROM Especialidade")
        resultado = cursor.fetchall()
        cursor.close()

        especialidades = []
        for id_especialidade, descricao in resultado:
            especialidades.append(Especialidade(descricao, id_especialidade))
        return especialidades

    def buscar_por_id(self, id_especialidade):
        cursor = self.conexao.cursor()
        cursor.execute(
            "SELECT id_especialidade, descricao FROM Especialidade WHERE id_especialidade = %s",
            (id_especialidade,)
        )
        registro = cursor.fetchone()
        cursor.close()

        if registro:
            return Especialidade(registro[1], registro[0])
        return None

    def atualizar(self, especialidade):
        cursor = self.conexao.cursor()
        sql = "UPDATE Especialidade SET descricao = %s WHERE id_especialidade = %s"
        cursor.execute(sql, (especialidade.descricao, especialidade.id_especialidade))
        self.conexao.commit()
        print("%s registro atualizado." % cursor.rowcount)
        cursor.close()

    def remover(self, id_especialidade):
        cursor = self.conexao.cursor()
        cursor.execute(
            "DELETE FROM Especialidade WHERE id_especialidade = %s",
            (id_especialidade,)
        )
        self.conexao.commit()
        print("%s registro removido." % cursor.rowcount)
        cursor.close()

def menu_adicionar(bd):
    descricao = input("Descrição da especialidade: ")
    nova = Especialidade(descricao)
    bd.inserir(nova)

def menu_listar(bd):
    for especialidade in bd.listar():
        print(especialidade)

def menu_buscar(bd):
    id_especialidade = input("ID da especialidade: ")
    especialidade = bd.buscar_por_id(id_especialidade)
    if especialidade:
        print(especialidade)
    else:
        print("Especialidade não encontrada.")
    return especialidade

def menu_atualizar(bd):
    especialidade = menu_buscar(bd)
    if especialidade:
        nova_descricao = input("Nova descrição [%s]: " % especialidade.descricao)
        especialidade.descricao = nova_descricao
        bd.atualizar(especialidade)

def menu_remover(bd):
    id_especialidade = input("ID da especialidade a remover: ")
    bd.remover(id_especialidade)

def menu_principal():
    bd = BancoDados()
    bd.conectar()

    if not bd.conexao:
        return

    while True:
        print("\nMENU DE CADASTRO DE ESPECIALIDADES")
        print("1 - Adicionar especialidade")
        print("2 - Listar todas as especialidades")
        print("3 - Buscar por uma especialidade")
        print("4 - Atualizar especialidade existente")
        print("5 - Remover especialidade")
        print("0 - Sair do programa")
        opcao = input("Digite uma opção: ")

        if opcao == "1":
            menu_adicionar(bd)
        elif opcao == "2":
            menu_listar(bd)
        elif opcao == "3":
            menu_buscar(bd)
        elif opcao == "4":
            menu_atualizar(bd)
        elif opcao == "5":
            menu_remover(bd)
        elif opcao == "0":
            break
        else:
            print("Opção inválida.")

    bd.desconectar()

if __name__ == "__main__":
    menu_principal()
